Azure Load Testingを使って、GitHub Actionsで負荷テストをおこなってみた
いわさです。
本記事はQiita Azure Advent Calendar 2021 10日目の記事です。
re:Invent2021の最中、Azureではなかなか熱いサービス「Azure Load Testing」がプレビューで登場しましたよ。
一言でいうとAzureフルマネージドなJMeterサービスです。
本日はこちらを触ってみたのと、マネージドサービスということもあってCI/CDワークフローに簡単に組み込めるようになったので、本日はGitHub Actionsで実行してみました。
本サービスは、本日時点でパブリックプレビューです。今後仕様が変わる可能性があります。
Azure Load Testingとは
Azureでホストされる、マネージドな負荷テストサービスです。
Apache JMeterのスクリプトを使って負荷テストを作成することが可能です。
従来JMeter用のインフラのために複数台の仮想マシン群などを用意していたケースも多いのではないかと思いますが、Azure Load Testingを使うとインフラの準備や管理が不要になり、すぐに負荷テストを開始することが可能です。
そしてテストを実行した時間など利用した分だけの料金なので負荷テストを行わずにインフラを待機させておくコストを考えなくて良くなります。
Azure Load Testingリソースだけ準備しておいて、必要な時にだけいつでも使うことが出来ます。
また、Azure Monitorと統合されており、テスト実行中のクライアントとサーバーのパフォーマンスを確認することが可能です。
対応リージョン
本日時点での対応リージョンは以下の5つとなっています。
- オーストラリア東部
- 米国中南部
- 米国東部
- 米国東部 2
- 北ヨーロッパ
料金
Azure Load Testingでは負荷テストリソースを作成し、そのリソースを使ってテストを行っていきます。
複数のテストでリソースは共有利用が可能です。
負荷テストリソース1つにつき、$10/月固定でまず発生します。
この費用には50時間分のVirtual User Hours(仮想ユーザー時間?)が含まれています。
負荷テストを実行する際に、負荷テストリソースの並列数を指定することが出来ます。
例えば、3台分の仮想ユーザーで2時間の負荷テストを実行した場合は6時間分のVirtual User Hoursを消費したことになります。
そして、50時間分を超えた場合は追加で1時間ごとの追加料金が発生する形です。
料金詳細は以下をご確認ください。
ちなみに、負荷テストリソース事態を複数作成した場合はそれぞれ$10から費用が発生します。
やってみる
まずはテストをどのような形で実行出来るのか確認してみたいと思います。
なお、本日は本格的な負荷テストは作成していません。動作確認が出来たらGitHub Actionsの設定にすすんでしまいたいと思います。
なので、Azure Load Testingnにはリソースモニタリングの機能などもあるのですが、こちらも本日はスルーしていきます。
また別のタイミングで色々なテストパターン用意した上でご紹介出来ればと思います。
リソース作成
Azure Load Testingリソース自体は数秒でセットアップされ、すぐに利用可能になります。
ロール割り当て
リソース作成直後は以下のようなメッセージが表示されます。
You are not authorized to use this resource, and need to be assigned the Load Test Owner, Load Test Contributor, or Load Test Reader role. The person assigning Azure roles needs to have Microsoft.Authorization/roleAssignments/write permissions, such as User Access Administrator or Owner. In case role was recently granted, please refresh the page and try again. Learn more
利用者に以下のロールから割り当てを行う必要があります。
- Load Test Contributor
- 負荷テストを表示、作成、更新、削除、および実行します。 負荷テストリソースを表示および一覧表示しますが、変更を加えることはできません。
- Load Test Owner
- 負荷テストリソースと負荷テストですべての操作を実行します
- Load Test Reader
- すべての負荷テストと負荷テストリソースを表示および一覧表示しますが、変更を加えることはできません
既存負荷テストリソースを利用するだけであればContributorの権限だけで良いです。
後ほど実施するGitHub Actions用のサービスプリンシパルにはContributorを割り当てています。
テスト作成
では、テストを作成します。
テストはApache JMeterのスクリプトファイル(*.jmx)をアップロードすることで作成します。
ですのでまずはスクリプトとテスト対象の環境を準備したいと思います。
テスト対象の環境はApp Serviceなどでサッと用意します。
JMeterスクリプトファイルは今回は実際にJMeterで上記テストサイトに1スレッドでGETリクエストを送信するだけのテストを設定し、テストファイルとしてダウンロードしました。
<?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.1"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> <boolProp name="TestPlan.functional_mode">false</boolProp> <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp> <boolProp name="TestPlan.serialize_threadgroups">false</boolProp> <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="TestPlan.user_define_classpath"></stringProp> </TestPlan> <hashTree> <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true"> <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> <boolProp name="LoopController.continue_forever">false</boolProp> <stringProp name="LoopController.loops">1</stringProp> </elementProp> <stringProp name="ThreadGroup.num_threads">1</stringProp> <stringProp name="ThreadGroup.ramp_time">1</stringProp> <boolProp name="ThreadGroup.scheduler">false</boolProp> <stringProp name="ThreadGroup.duration"></stringProp> <stringProp name="ThreadGroup.delay"></stringProp> <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp> </ThreadGroup> <hashTree> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="HTTPSampler.domain">20211210hoge.azurewebsites.net</stringProp> <stringProp name="HTTPSampler.port"></stringProp> <stringProp name="HTTPSampler.protocol">https</stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> </HTTPSamplerProxy> <hashTree/> </hashTree> </hashTree> </hashTree> </jmeterTestPlan>
Create Test
からスクリプトをアップロードしましょう。
オプションで設定可能なパラメーターは今回はスキップします。
詳細は以下をご確認ください。
Load
タブでは、JMeterスクリプトを何台のインスタンスで並列実行するかを設定出来ます。
スレッド数ではないです。
スクリプトで設定したスレッド数が10と定義されていて、Loadタブで20台のインスタンスを設定したとすると、200スレッドのテストが実行されます。 なお、プレビュー時点では、最大45インスタンスが上限となっています。
次はテスト基準です。
負荷テストを実施した結果をAzure Load TestingでOK/NGの判定を行うことが可能です。
本日時点で設定可能な基準値はレスポンスタイムとエラーレートの2つとなっています。
テスト実行
テスト作成後に自動実行されるようにも設定できますし、作成したテストを明示的に実行することも可能です。
実行するとテスト完了までインジゲータが表示されます。
テスト結果が表示されました。
トータルリクエスト数からレスポンスタイム、エラーレート、あとスループットもサマリで表示されますね。
まずは、Azure Load Testingでテストを実行することが出来ました。やった。
GitHub Actionsに組み込んでみる
さて、ではここからは同じようなテストをGitHub Actionsで実行してみましょう。
コードがデプロイされるごとに負荷テストを実行するようなイメージを想定しています。
まず、GitHub Actions用のAzure Load Testingアクションが既に提供されていますのでそちらを利用します。
サービスプリンシパルの準備
利用にあたって、Azureのクレデンシャルが必要になるので作成しましょう。
このアクションはazure/login@v1
した認証をそのまま利用出来るみたいなので、以前ためしたようなOIDCでの認証いけると思います。
サービスプリンシパルの作成とロールの割り当てを行います。
PS /home/iwasa_takahito> az ad sp create-for-rbac --name iwasa-load-test1 --role contributor --scopes /subscriptions/11111111-2222-3333-4444-555555555555/resourceGroups/20211203 --sdk-auth PS /home/iwasa_takahito> az ad sp list --filter "displayname eq 'iwasa-load-test1'" -o table PS /home/iwasa_takahito> az role assignment create --assignee "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE" --role "Load Test Contributor" --subscription "11111111-2222-3333-4444-555555555555"
上記コマンドの実行過程で、クレデンシャルが発行されるのでGitHub Secretsに登録しておきます。
作成後、サービスプリンシパルにロールが割りあたっているか、Azureポータルから確認してみました。
良さそうですね。
負荷テストスクリプトとワークフローの設定
先程Azure Load Testingを手動実行した際の結果画面で、Resultのダウンロードが可能です。
ダウンロードしたファイルの中にはインプットとなるJMeterスクリプトと、それと紐づくAzure Load Testingの設定ファイルが含まれています。
今回はこの2つを使ってみましょう。(インスタンスを2台にし、テスト名を変更してみました。)
testName: hoge testPlan: iwasa-jmeter1.jmx description: '' engineInstances: 2
そしてワークフローでAzure Load Testingアクションを構成します。
name: CI on: push: branches: [ main ] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Login to Azure uses: azure/login@v1 continue-on-error: false with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: 'Azure Load Testing' uses: azure/load-testing@v1 with: loadTestConfigFile: 'config.yaml' loadTestResource: 'iwasa-load-test1' resourceGroup: '20211203' - uses: actions/upload-artifact@v2 with: name: loadTestResults path: ${{ github.workspace }}/loadTest
後処理で負荷テストの結果ファイルを取得しています。
ワークフロー実行
では、いよいよワークフローを実行してみましょう。
マネジメントコンソールで確認してみます。
テストが作成されていますね。
ワークフローの実行結果から負荷テストの結果ファイルをダウンロード出来ます。
Apache JMeterのダッシュボードの形でレポートを確認することが出来ます。
便利ですね!
さいごに
本日はパブリックプレビューで登場した、Azure Load TestingをGitHub Actionsから利用してみました。
かなり簡単に利用できますね。
そして、マネージドな負荷テストツールということでかなり期待したいサービスです。
対象サービスは、Azureじゃなくても利用出来るようなので。活用したいシーンは結構多いかもしれないです。
まだミニマムなテストを実行してみたくらいな段階なので、もう少し色々なテストパターンを試していってみたいと思います。